// #include <iostream>
// #include "usart.h"
// #include <opencv2/opencv.hpp>
// #include "CSerialPort/SerialPort.h"
// #include "CSerialPort/SerialPortInfo.h"

// #include <unistd.h>
// #include <vector>
// #define imsleep(microsecond) usleep(1000 * microsecond) // ms
// using namespace cv;
// using namespace std;
// using namespace itas109;
// // extern uint8_t fuck;
// uint8_t fffflag;
// class MyListener : public CSerialPortListener
// {
// public:
//     MyListener(CSerialPort *sp)
//         : p_sp(sp) {};

//     void onReadEvent(const char *portName, unsigned int readBufferLen)
//     {
//         if (readBufferLen > 0)
//         {
//             int recLen = p_sp->readData(data_buffer, readBufferLen > 50 ? 50 : readBufferLen);
//             for (size_t i = 0; i < recLen; i++)
//             {
//                 Receive(data_buffer[i]);
//             }
//         }
//     };

// private:
//     CSerialPort *p_sp;
//     uint8_t data_buffer[50];
// };
// extern DATA datatest;
// int main()
// {
//     CSerialPort sp;
//     MyListener listener(&sp);
//     std::vector<SerialPortInfo> m_availablePortsList = CSerialPortInfo::availablePortInfos();
//     sp.init(m_availablePortsList[1].portName, // windows:COM1 Linux:/dev/ttyS0
//             itas109::BaudRate115200,          // baudrate
//             itas109::ParityNone,              // parity
//             itas109::DataBits8,               // data bit
//             itas109::StopOne,                 // stop bit
//             itas109::FlowNone,                // flow
//             4096                              // read buffer size
//     );
//     sp.setReadIntervalTimeout(1);                    // read interval timeout 0ms
//     sp.setByteReadBufferFullNotify(sizeof(fffflag)); // buffer full notify
//     sp.open();
//     sp.connectReadEvent(&listener);
//     datatest.head[0] = HEAD1;
//     datatest.head[1] = HEAD2;
//     datatest.cmd = 4;
//     datatest.len = 1;
//     datatest.tail = TAIL;
//     int l = 0;
//     datatest.dataf = l + 1;
//     sp.writeData(&datatest, sizeof(datatest));
//     for (;;)
//     {
//         imsleep(1);
//         // printf("fuck:%d\r\n", fuck);
//     }
//     return 0;
// }

#include <iostream>
#include <vector>
#include <algorithm>
#include "usart.h"
#include <opencv2/opencv.hpp>
#include "CSerialPort/SerialPort.h"
#include "CSerialPort/SerialPortInfo.h"
#include <unistd.h>
#define imsleep(microsecond) usleep(1000 * microsecond) // ms
using namespace std;
using namespace cv;
using namespace itas109;

class MyListener : public CSerialPortListener
{
public:
    MyListener(CSerialPort *sp)
        : p_sp(sp) {};

    void onReadEvent(const char *portName, unsigned int readBufferLen)
    {
        if (readBufferLen > 0)
        {
            int recLen = p_sp->readData(data_buffer, readBufferLen > 50 ? 50 : readBufferLen);
            for (size_t i = 0; i < recLen; i++)
            {
                Receive(data_buffer[i]);
            }
        }
    };

private:
    CSerialPort *p_sp;
    uint8_t data_buffer[50];
};
// 变量=========================================================================================================================
extern DATA datatest;
uint8_t fffflag;
extern uint8_t isAction;
extern uint8_t isBlack;
extern uint8_t isWhite;
extern uint8_t isPlayerDown;
//=========================================================================================================================
// 定义棋盘大小
const int BOARD_SIZE = 3;

// 定义棋子类型
enum Player
{
    EMPTY,
    X,
    O
};

// 打印棋盘
void printBoard(const vector<vector<Player>> &board)
{
    for (const auto &row : board)
    {
        for (const auto &cell : row)
        {
            switch (cell)
            {
            case EMPTY:
                cout << ".";
                break;
            case X:
                cout << "X";
                break;
            case O:
                cout << "O";
                break;
            }
            cout << " ";
        }
        cout << endl;
    }
}

// 检查游戏是否结束
bool isGameOver(const vector<vector<Player>> &board)
{
    // 检查行
    for (const auto &row : board)
    {
        if (row[0] != EMPTY && all_of(row.begin(), row.end(), [&](Player p)
                                      { return p == row[0]; }))
        {
            return true;
        }
    }
    // 检查列
    for (int col = 0; col < BOARD_SIZE; ++col)
    {
        if (board[0][col] != EMPTY && all_of(board.begin(), board.end(), [&](const vector<Player> &row)
                                             { return row[col] == board[0][col]; }))
        {
            return true;
        }
    }
    // 检查对角线
    if (board[0][0] != EMPTY && all_of(board.begin(), board.end(), [&](const vector<Player> &row)
                                       { return row[&row - &board[0]] == board[0][0]; }))
    {
        return true;
    }
    if (board[0][BOARD_SIZE - 1] != EMPTY && all_of(board.begin(), board.end(), [&](const vector<Player> &row)
                                                    { return row[BOARD_SIZE - 1 - (&row - &board[0])] == board[0][BOARD_SIZE - 1]; }))
    {
        return true;
    }
    // 检查是否平局
    for (const auto &row : board)
    {
        if (any_of(row.begin(), row.end(), [](Player p)
                   { return p == EMPTY; }))
        {
            return false;
        }
    }
    return true;
}

// 评估棋盘得分
int evaluateBoard(const vector<vector<Player>> &board, Player player)
{
    // 检查行
    for (const auto &row : board)
    {
        if (row[0] != EMPTY && all_of(row.begin(), row.end(), [&](Player p)
                                      { return p == row[0]; }))
        {
            return row[0] == player ? 10 : -10;
        }
    }
    // 检查列
    for (int col = 0; col < BOARD_SIZE; ++col)
    {
        if (board[0][col] != EMPTY && all_of(board.begin(), board.end(), [&](const vector<Player> &row)
                                             { return row[col] == board[0][col]; }))
        {
            return board[0][col] == player ? 10 : -10;
        }
    }
    // 检查对角线
    if (board[0][0] != EMPTY && all_of(board.begin(), board.end(), [&](const vector<Player> &row)
                                       { return row[&row - &board[0]] == board[0][0]; }))
    {
        return board[0][0] == player ? 10 : -10;
    }
    if (board[0][BOARD_SIZE - 1] != EMPTY && all_of(board.begin(), board.end(), [&](const vector<Player> &row)
                                                    { return row[BOARD_SIZE - 1 - (&row - &board[0])] == board[0][BOARD_SIZE - 1]; }))
    {
        return board[0][BOARD_SIZE - 1] == player ? 10 : -10;
    }
    return 0;
}

// MiniMax算法
int miniMax(vector<vector<Player>> &board, int depth, bool isMax, Player player)
{
    int score = evaluateBoard(board, player);
    if (score == 10)
        return score - depth;
    if (score == -10)
        return score + depth;
    if (isGameOver(board))
        return 0;

    if (isMax)
    {
        int best = -1000;
        for (int i = 0; i < BOARD_SIZE; ++i)
        {
            for (int j = 0; j < BOARD_SIZE; ++j)
            {
                if (board[i][j] == EMPTY)
                {
                    board[i][j] = player;
                    best = max(best, miniMax(board, depth + 1, !isMax, player));
                    board[i][j] = EMPTY;
                }
            }
        }
        return best;
    }
    else
    {
        int best = 1000;
        for (int i = 0; i < BOARD_SIZE; ++i)
        {
            for (int j = 0; j < BOARD_SIZE; ++j)
            {
                if (board[i][j] == EMPTY)
                {
                    board[i][j] = (player == X ? O : X);
                    best = min(best, miniMax(board, depth + 1, !isMax, player));
                    board[i][j] = EMPTY;
                }
            }
        }
        return best;
    }
}

// 找到最佳移动
pair<int, int> findBestMove(vector<vector<Player>> &board, Player player)
{
    int bestVal = -1000;
    pair<int, int> bestMove = {-1, -1};

    for (int i = 0; i < BOARD_SIZE; ++i)
    {
        for (int j = 0; j < BOARD_SIZE; ++j)
        {
            if (board[i][j] == EMPTY)
            {
                board[i][j] = player;
                int moveVal = miniMax(board, 0, false, player);
                board[i][j] = EMPTY;
                if (moveVal > bestVal)
                {
                    bestMove = {i, j};
                    bestVal = moveVal;
                }
            }
        }
    }
    return bestMove;
}
// 获取第几行第几列
std::pair<int, int> get_position(const std::vector<std::vector<int>> &matrix, int element_index)
{
    int total_rows = matrix.size();
    if (total_rows == 0)
    {
        throw std::invalid_argument("Matrix is empty.");
    }
    int total_cols = matrix[0].size();
    if (total_cols == 0)
    {
        throw std::invalid_argument("Matrix has empty rows.");
    }

    // 计算总元素个数
    int total_elements = total_rows * total_cols;
    if (element_index < 0 || element_index >= total_elements)
    {
        throw std::out_of_range("Element index is out of range.");
    }

    // 计算行和列
    int row = element_index / total_cols;
    int col = element_index % total_cols;

    return std::make_pair(row, col);
}
// 获取第几个
int get_element(const std::vector<std::vector<int>> &matrix, int row, int col)
{
    return matrix[row][col];
}

// 比较函数，用于根据矩形的左上角坐标进行排序
bool compareRects(const cv::Rect &a, const cv::Rect &b)
{
    if (a.y != b.y)
        return a.y < b.y;
    return a.x < b.x;
}
bool compareRects(const cv::Rect &a, const cv::Rect &b)
{
    // 计算右上角坐标
    int rightA = a.x + a.width;
    int rightB = b.x + b.width;

    if (a.y != b.y)
        return a.y < b.y;
    return rightA < rightB;
}
// 计算两个点之间的欧几里得距离
double distance(const cv::Point &p1, const cv::Point &p2)
{
    return std::sqrt(std::pow(p1.x - p2.x, 2) + std::pow(p1.y - p2.y, 2));
}
// 返回被占用矩形的索引
std::vector<int> findOccupiedRectangles(const std::vector<cv::Point> &rectangleCenter, const std::vector<cv::Point> &largeCirclesCenters)
{
    // static uint32_t count;
    // count++;
    // std::cout << "run findOccupiedRectangles:" << count << std::endl;
    std::vector<int> occupiedIndices;
    if (largeCirclesCenters.empty())
    {
        occupiedIndices.clear();
        return occupiedIndices;
    }
    else
    {
        // 遍历每个棋子坐标
        for (const auto &circleCenter : largeCirclesCenters)
        {
            double minDistance = std::numeric_limits<double>::max();
            int closestIndex = -1;

            // 找到距离最近的矩形中心坐标
            for (size_t i = 0; i < rectangleCenter.size(); ++i)
            {
                double dist = distance(circleCenter, rectangleCenter[i]);
                if (dist < minDistance)
                {
                    minDistance = dist;
                    closestIndex = i;
                }
            }

            // 如果找到最近的矩形，且该矩形未被标记为占用，则标记并记录索引
            if (closestIndex != -1 && std::find(occupiedIndices.begin(), occupiedIndices.end(), closestIndex) == occupiedIndices.end())
            {
                occupiedIndices.push_back(closestIndex);
            }
        }

        return occupiedIndices;
    }
}
cv::Point rotatePoint(const cv::Point &begainMid, const cv::Point &buffMid, double theta)
{
    // 将角度转换为弧度
    double thetaRad = theta * M_PI / 180.0;

    // 计算旋转后的新坐标
    double cosTheta = std::cos(thetaRad);
    double sinTheta = std::sin(thetaRad);

    double x = begainMid.x - buffMid.x;
    double y = begainMid.y - buffMid.y;

    double xPrime = x * cosTheta - y * sinTheta + buffMid.x;
    double yPrime = x * sinTheta + y * cosTheta + buffMid.y;

    return cv::Point(cvRound(xPrime), cvRound(yPrime));
}
//====================================================================================================================================
CSerialPort sp;
uint16_t CRC16_Check(const uint8_t *data, uint8_t len)
{
    uint16_t CRC16 = 0xFFFF;
    uint8_t state, i, j;
    for (i = 0; i < len; i++)
    {
        CRC16 ^= data[i];
        for (j = 0; j < 8; j++)
        {
            state = CRC16 & 0x01;
            CRC16 >>= 1;
            if (state)
            {
                CRC16 ^= 0xA001;
            }
        }
    }
    return CRC16;
}
void Send_Cmd_Data(uint8_t cmd, const uint8_t *datas, uint8_t len)
{
    uint8_t buf[300], i, cnt = 0;
    uint16_t crc16;
    buf[cnt++] = 0xA5;
    buf[cnt++] = 0x5A;
    buf[cnt++] = len;
    buf[cnt++] = cmd;
    for (i = 0; i < len; i++)
    {
        buf[cnt++] = datas[i];
    }
    crc16 = CRC16_Check(buf, len + 4);
    buf[cnt++] = crc16 >> 8;
    buf[cnt++] = crc16 & 0xFF;
    buf[cnt++] = 0xFF;
    // Send(buf, cnt); // 调用数据帧发送函数将打包好的数据帧发送出去
    sp.writeData(buf, 7 + len);
}
// x黑先下 O白后下
int main()
{

    MyListener listener(&sp);
    std::vector<SerialPortInfo> m_availablePortsList = CSerialPortInfo::availablePortInfos();
    sp.init(m_availablePortsList[1].portName, // windows:COM1 Linux:/dev/ttyS0
            itas109::BaudRate115200,          // baudrate
            itas109::ParityNone,              // parity
            itas109::DataBits8,               // data bit
            itas109::StopOne,                 // stop bit
            itas109::FlowNone,                // flow
            4096                              // read buffer size
    );
    sp.setReadIntervalTimeout(1);                    // read interval timeout 0ms
    sp.setByteReadBufferFullNotify(sizeof(fffflag)); // buffer full notify
    sp.open();
    sp.connectReadEvent(&listener);
    datatest.head[0] = HEAD1;
    datatest.head[1] = HEAD2;
    datatest.len = 4;
    datatest.tail = 0x7E;
    // datatest.dataf = -100.0f;
    // datatest.cmd = 19;
    // sp.writeData(&datatest, sizeof(datatest));
    // Send_Cmd_Data(19, (const uint8_t *)(&datass), 1);
    // cam初始化
    VideoCapture cap(0);
    if (!cap.isOpened())
    {
        cout << "无法打开摄像头" << endl;
        return -1;
    }
    cap.set(cv::CAP_PROP_FRAME_WIDTH, 640);
    cap.set(cv::CAP_PROP_FRAME_HEIGHT, 480);
    Mat frame, result, gray, edges, openedImage, result2, openedImage2, img, gray1, gray2;
    cv::Mat kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3));
    cv::Mat kernel2 = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5, 5));
    std::vector<std::vector<cv::Point>> contours;
    std::vector<cv::Vec4i> hierarchy;
    // 存储检测到的矩形
    std::vector<cv::Rect> rectangles;
    int maxRectangles = 9;
    int HSVFlag = 0;
    // 定义9种颜色
    vector<Scalar> colors = {
        Scalar(0, 0, 255),   // 红色
        Scalar(0, 255, 0),   // 绿色
        Scalar(255, 0, 0),   // 蓝色
        Scalar(0, 255, 255), // 黄色
        Scalar(255, 0, 255), // 紫色
        Scalar(255, 255, 0), // 青色
        Scalar(128, 0, 128), // 深紫色
        Scalar(0, 128, 128), // 深青色
        Scalar(128, 128, 0)  // 深黄色
    };
    // 定义黑色区域的HSV范围
    Scalar lower_black = Scalar(91, 0, 105);
    Scalar upper_black = Scalar(99, 255, 255);
    // 处理棋子
    vector<Point> whitePieces;
    vector<Point> blackPieces;
    // 定义目标大小
    cv::Size newSize(640, 480); // 将图像缩小一半
    std::vector<cv::Point> rectangleCenter;
    // 获取被占用矩形的索引
    std::vector<int> occupiedIndices, occupiedIndicesLast;
    // 找出不同的元素
    std::vector<int> playerPosition;
    std::vector<std::vector<int>> data = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}};
    vector<vector<Player>> board(BOARD_SIZE, vector<Player>(BOARD_SIZE, EMPTY));
    Player currentPlayer;
    // isBlack = 0;
    // isWhite = 0;
    // isAction = 0;
    uint8_t isDown = 0;
    uint8_t isEnd = 0;
    uint8_t reflash = 0;
    float averageAngle;
    uint8_t convertionFlag = 0;
    while (true)
    {

        if (HSVFlag == 0)
        {
            cap >> frame;
            if (frame.empty())
            {
                break;
            }

            // cv::resize(img, frame, newSize, 0, 0, cv::INTER_LINEAR);
            // 转换为HSV颜色空间
            Mat hsv;
            cvtColor(frame, hsv, COLOR_BGR2HSV);
            // 创建掩码
            Mat mask;
            inRange(hsv, lower_black, upper_black, mask);
            // 形态学操作
            cv::morphologyEx(mask, mask, cv::MORPH_CLOSE, kernel);
            cv::findContours(mask, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);
            rectangles.clear();
            for (size_t i = 0; i < contours.size(); ++i)
            {
                // 近似轮廓
                std::vector<cv::Point> approx;
                cv::approxPolyDP(contours[i], approx, cv::arcLength(contours[i], true) * 0.02, true);

                // 如果是四边形且是凸的
                if (approx.size() == 4 && cv::isContourConvex(approx))
                {
                    double area = contourArea(approx);
                    Rect rect = boundingRect(approx);
                    if (area > 2000 && area < 20000)
                    { // 面积阈值，可以根据实际情况调整
                        // 绘制矩形
                        bool tooClose = false;
                        for (const auto &existingRect : rectangles)
                        {
                            // 检查新矩形是否与现有矩形太接近
                            if (abs(rect.x - existingRect.x) < 5 && abs(rect.y - existingRect.y) < 5)
                            {
                                tooClose = true;
                                break;
                            }
                        }
                        if (!tooClose)
                        {
                            std::cout << "pixel count " << area << std::endl;
                            rectangles.push_back(rect);
                        }
                        if (rectangles.size() >= maxRectangles)
                        {
                            break;
                        }
                    }
                }
                for (size_t i = 0; i < rectangles.size(); ++i)
                {
                    cv::rectangle(frame, rectangles[i], colors[i % colors.size()], 2);
                }
            }
            // // 对矩形进行排序
            std::sort(rectangles.begin(), rectangles.end(), compareRects);
            // 绘制矩形框并标记数字
            std::vector<cv::Point> rectangleCenterBuff;
            for (size_t i = 0; i < rectangles.size(); ++i)
            {
                cv::rectangle(frame, rectangles[i], colors[i % colors.size()], 2);
                // 计算矩形中心位置
                int centerX = rectangles[i].x + rectangles[i].width / 2;
                int centerY = rectangles[i].y + rectangles[i].height / 2;
                cv::Point center(cvRound(centerX), cvRound((centerY)));
                rectangleCenterBuff.push_back(center);
                // 绘制数字
                putText(frame, to_string(i + 1), Point(centerX, centerY), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 0, 0), 2);
            }

            imshow("Original Frame", frame);
            imshow("Result Image", mask);
            // imshow("Opened Image", openedImage);
            // imshow("gray Image", gray);
            if (waitKey(1) == 27)
            {
                rectangleCenter = rectangleCenterBuff;
                HSVFlag = 1;
            }
        }
        else if (HSVFlag == 1)
        {
            cap >> frame;
            if (frame.empty())
            {
                break;
            }

            // cv::resize(img, frame, newSize, 0, 0, cv::INTER_LINEAR);
            // 转换为HSV颜色空间
            Mat hsv;
            cvtColor(frame, hsv, COLOR_BGR2HSV);
            // 创建掩码
            Mat mask;
            inRange(hsv, lower_black, upper_black, mask);
            // 形态学操作
            cv::morphologyEx(mask, mask, cv::MORPH_CLOSE, kernel);
            cv::findContours(mask, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);
            rectangles.clear();
            std::vector<cv::RotatedRect> minRects; // 存储旋转矩形
            for (size_t i = 0; i < contours.size(); ++i)
            {
                // 近似轮廓
                std::vector<cv::Point> approx;
                cv::approxPolyDP(contours[i], approx, cv::arcLength(contours[i], true) * 0.02, true);

                // 如果是四边形且是凸的
                if (approx.size() == 4 && cv::isContourConvex(approx))
                {
                    double area = contourArea(approx);
                    Rect rect = boundingRect(approx);
                    if (area > 2000 && area < 20000)
                    { // 面积阈值，可以根据实际情况调整
                        // 绘制矩形
                        bool tooClose = false;
                        for (const auto &existingRect : rectangles)
                        {
                            // 检查新矩形是否与现有矩形太接近
                            if (abs(rect.x - existingRect.x) < 5 && abs(rect.y - existingRect.y) < 5)
                            {
                                tooClose = true;
                                break;
                            }
                        }
                        if (!tooClose)
                        {
                            std::cout << "pixel count " << area << std::endl;
                            rectangles.push_back(rect);
                            // 获取旋转矩形
                            minRects.push_back(minAreaRect(approx));
                        }
                        if (rectangles.size() >= maxRectangles)
                        {
                            break;
                        }
                    }
                }
                float totalAngle = 0.0f; // 用于累加所有旋转矩形的角度
                int rectCount = 0;       // 用于记录旋转矩形的数量

                // 打印旋转矩形信息并计算平均旋转角
                for (size_t i = 0; i < minRects.size(); ++i)
                {
                    cv::Point2f rect_points[4];
                    minRects[i].points(rect_points);
                    std::cout << "Rotated Rectangle " << i + 1 << ":" << std::endl;
                    std::cout << "  Center: (" << minRects[i].center.x << ", " << minRects[i].center.y << ")" << std::endl;
                    std::cout << "  Size: (" << minRects[i].size.width << ", " << minRects[i].size.height << ")" << std::endl;
                    if (minRects[i].angle > 45)
                    {
                        minRects[i].angle -= 90;
                    }
                    std::cout << "  Angle: " << minRects[i].angle << " degrees" << std::endl;
                    std::cout << "  Points: ";
                    for (int j = 0; j < 4; j++)
                    {
                        std::cout << "(" << rect_points[j].x << ", " << rect_points[j].y << ") ";
                    }
                    std::cout << std::endl;

                    // 累加旋转角度
                    if (i != 0)
                    {
                        totalAngle += minRects[i].angle;
                        rectCount++;
                    }

                    // 绘制旋转矩形
                    std::vector<cv::Point2f> vertices(4);
                    minRects[i].points(vertices.data());
                    std::vector<cv::Point> int_vertices;
                    for (const auto &v : vertices)
                    {
                        int_vertices.push_back(cv::Point(cvRound(v.x), cvRound(v.y)));
                    }
                    cv::polylines(frame, int_vertices, true, cv::Scalar(0, 255, 0), 2);

                    // 标注旋转角度
                    std::string angleText = std::to_string(minRects[i].angle) + " deg";
                    cv::Point textPosition(minRects[i].center.x - 20, minRects[i].center.y);
                    cv::putText(frame, angleText, textPosition, cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 2);
                }
                // 计算平均旋转角
                if (rectCount > 0)
                {
                    averageAngle = totalAngle / rectCount;
                    std::cout << "Average Rotation Angle: " << averageAngle << " degrees" << std::endl;
                }
                else
                {
                    std::cout << "No rotated rectangles detected." << std::endl;
                }
                for (size_t i = 0; i < rectangles.size(); ++i)
                {
                    cv::rectangle(frame, rectangles[i], colors[i % colors.size()], 2);
                }
            }
            // // 对矩形进行排序
            std::sort(rectangles.begin(), rectangles.end(), compareRects);
            // 绘制矩形框并标记数字
            std::vector<cv::Point> rectangleCenterBuff;
            for (size_t i = 0; i < rectangles.size(); ++i)
            {
                cv::rectangle(frame, rectangles[i], colors[i % colors.size()], 2);
                // 计算矩形中心位置
                int centerX = rectangles[i].x + rectangles[i].width / 2;
                int centerY = rectangles[i].y + rectangles[i].height / 2;
                cv::Point center(cvRound(centerX), cvRound((centerY)));
                rectangleCenterBuff.push_back(center);
                // 绘制数字
                putText(frame, to_string(i + 1), Point(centerX, centerY), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 0, 0), 2);
            }
            imshow("task3Frame", frame);
            imshow("task3Mas", mask);
            // imshow("Opened Image", openedImage);
            // imshow("gray Image", gray);
            if (waitKey(1) == 27)
            {
                convertionFlag = 1;
                // HSVFlag = 2;
            }
            if (convertionFlag == 1)
            {
                cv::Point buffMid = rectangleCenterBuff[4];
                cv::Point begainMid = rectangleCenter[4];
                // 计算buffMid和begainMid之间的x和y差值
                int dx = buffMid.x - begainMid.x;
                int dy = buffMid.y - begainMid.y;
                // 将rectangleCenter中的点全部根据差值平移
                std::vector<cv::Point> rectangleCenterBuff2;
                rectangleCenterBuff2 = rectangleCenter;
                for (size_t i = 0; i < rectangleCenterBuff2.size(); ++i)
                {
                    rectangleCenterBuff2[i].x += dx;
                    rectangleCenterBuff2[i].y += dy;
                }
                // 在图像中绘制平移后的点
                for (size_t i = 0; i < rectangleCenterBuff2.size(); ++i)
                {
                    cv::circle(frame, rectangleCenterBuff2[i], 5, cv::Scalar(255, 0, 0), -1); // 绘制平移后的点，青色
                }
                std::vector<cv::Point> rotatedRectangleCenter;
                for (size_t i = 0; i < rectangleCenterBuff2.size(); ++i)
                {
                    cv::Point rotatedPoint = rotatePoint(rectangleCenterBuff2[i], rectangleCenterBuff2[4], averageAngle);
                    rotatedRectangleCenter.push_back(rotatedPoint);
                }
                // 在图像中绘制旋转后的点
                for (size_t i = 0; i < rotatedRectangleCenter.size(); ++i)
                {
                    cv::circle(frame, rotatedRectangleCenter[i], 5, cv::Scalar(0, 255, 255), -1); // 绘制旋转后的点，黄色
                }
                // vector<int> xBuff, yBuff;
                // for (size_t i = 0; i < rectangleCenterBuff2.size(); ++i)
                // {
                //     int dx = rotatedRectangleCenter[i].x - rectangleCenterBuff2[i].x;
                //     int dy = rotatedRectangleCenter[i].y - rectangleCenterBuff2[i].y;

                //     int xPulse = -dx * 70; // 1个像素点差值要发50个脉冲
                //     int yPulse = -dy * 52; // 1个像素点差值要发50个脉冲
                //     xBuff.push_back(xPulse);
                //     yBuff.push_back(yPulse);
                //     std::cout << "Point " << i + 1 << ": dx = " << dx << ", dy = " << dy << ", xPulse = " << xPulse << ", yPulse = " << yPulse << std::endl;
                // }
                datatest.cmd = 19;
                datatest.dataf = averageAngle;
                sp.writeData(&datatest, sizeof(datatest));
                // datatest.cmd = 20;
                // datatest.dataf = yBuff[0];
                // sp.writeData(&datatest, sizeof(datatest));
                // printf("xBuff[0]:0x%x,  %d\r\n", xBuff[0], xBuff[0]);
                // printf("yBuff[0]:0x%x, %d\r\n", yBuff[0], yBuff[0]);
                // sp.writeData(&txdata, sizeof(txdata));
                // sp.writeData(&txdata.head[1], sizeof(txdata.head[1]));
                // sp.writeData(&txdata.geNum, sizeof(txdata.geNum));
                // sp.writeData(&txdata.xBuff, sizeof(txdata.xBuff));
                // sp.writeData(&txdata.yBuff, sizeof(txdata.yBuff));
                // sp.writeData(&txdata.tail, sizeof(txdata.tail));
                // cv::Point converPoint = rotatePoint(begainMid, buffMid, averageAngle);
                imshow("task3Frame2", frame);
                imshow("task3Mas2", mask);
                if (waitKey(1) == 27)
                {
                }
                HSVFlag = 2;
            }
            // HSVFlag = 2;
        }
        //=================================================================================================================================
        else if (HSVFlag == 2 && isAction == 0)
        {
            std::cout << "111111111111111111111111" << std::endl;
            if (isBlack == 1 && isWhite == 0)
            {
                // std::cout << "inTask4" << std::endl;
                isEnd = 1;
                currentPlayer = O;
            }
            if (isBlack == 0 && isWhite == 1)
            {
                isEnd = 1;
                currentPlayer = X;
            }
            // uint32_t count2;
            while (!isGameOver(board))
            {

                // while (isPlayerDown == 0)
                // {
                // }
                if (capCam == 1)
                {
                    capCam = 0;
                    reflash = 1;
                    cap >> frame;
                    // count2++;
                    // std::cout << "run cap:" << count2 << std::endl;
                    if (frame.empty())
                    {
                        break;
                    }
                }
                if (isPlayerDown == 1)
                {
                    // std::cout << "rectangleCenter:" << rectangleCenter << std::endl;
                    // 创建一个与原始帧大小相同的空白图像
                    result = Mat::zeros(frame.size(), CV_8UC3);
                    result2 = Mat::zeros(frame.size(), CV_8UC3);
                    // 遍历图像的每个像素点Mat::zeros(frame.size(), CV_8UC3);
                    if (isBlack == 1 && isWhite == 0)
                    {
                        for (int y = 0; y < frame.rows; y++)
                        {
                            for (int x = 0; x < frame.cols; x++)
                            {
                                // 获取当前像素点的RGB值
                                Vec3b pixel = frame.at<Vec3b>(y, x);
                                int b = pixel[0];
                                int g = pixel[1];
                                int r = pixel[2];

                                // 计算RGB值的和
                                int sum = r + g + b;

                                // 如果RGB值的和大于600，则将该像素点标记为白色
                                // 白色
                                if ((sum > 150) && r > 30)
                                {
                                    result.at<Vec3b>(y, x) = Vec3b(255, 255, 255);
                                }
                                // 黑色
                                // else if (sum < 80 && r < 25 && r > 0)
                                // {
                                //     result2.at<Vec3b>(y, x) = Vec3b(255, 255, 255);
                                // }
                            }
                        }
                        // 形态学操作
                        cv::morphologyEx(result, openedImage, cv::MORPH_CLOSE, kernel);

                        cv::cvtColor(openedImage, gray1, cv::COLOR_BGR2GRAY);
                        // 高斯模糊
                        cv::GaussianBlur(gray1, gray1, cv::Size(5, 5), 0);
                    }
                    if (isBlack == 0 && isWhite == 1)
                    {
                        for (int y = 0; y < frame.rows; y++)
                        {
                            for (int x = 0; x < frame.cols; x++)
                            {
                                // 获取当前像素点的RGB值
                                Vec3b pixel = frame.at<Vec3b>(y, x);
                                int b = pixel[0];
                                int g = pixel[1];
                                int r = pixel[2];

                                // 计算RGB值的和
                                int sum = r + g + b;

                                // 如果RGB值的和大于600，则将该像素点标记为白色
                                // 白色
                                // if ((sum > 150) && r > 30)
                                // {
                                //     result.at<Vec3b>(y, x) = Vec3b(255, 255, 255);
                                // }
                                // 黑色
                                if (sum < 80 && r < 25 && r > 0)
                                {
                                    result2.at<Vec3b>(y, x) = Vec3b(255, 255, 255);
                                }
                            }
                        }
                        // 形态学操作
                        cv::morphologyEx(result2, openedImage2, cv::MORPH_OPEN, kernel2);
                        cv::morphologyEx(result2, openedImage2, cv::MORPH_CLOSE, kernel2);
                        cv::cvtColor(openedImage2, gray2, cv::COLOR_BGR2GRAY);
                        // 高斯模糊
                        cv::GaussianBlur(gray2, gray2, cv::Size(9, 9), 0);
                    }
                    // 白色
                    std::vector<cv::Vec3f> circles;
                    if (isBlack == 1 && isWhite == 0)
                    {
                        HoughCircles(gray1, circles, HOUGH_GRADIENT, 1, 80, 40, 20, 20, 40);
                    }
                    std::vector<cv::Point> largeCirclesCenters;
                    // 黑色
                    std::vector<cv::Vec3f> circles2;
                    if (isBlack == 0 && isWhite == 1)
                    {
                        HoughCircles(gray2, circles2, HOUGH_GRADIENT, 1, 80, 30, 15, 15, 40);
                    }
                    std::vector<cv::Point> largeCirclesCenters2;
                    if (isBlack == 1 && isWhite == 0)
                    {
                        // 白色
                        for (const auto &circle : circles)
                        {
                            cv::Point center(cvRound(circle[0]), cvRound(circle[1]));
                            int radius = cvRound(circle[2]);
                            int area = CV_PI * radius * radius;
                            if (area > 2500)
                            {
                                largeCirclesCenters.push_back(center);
                                // 绘制圆形中心
                                cv::circle(frame, center, 3, cv::Scalar(0, 255, 0), -1, 8, 0);
                                // 绘制圆形轮廓
                                cv::circle(frame, center, radius, cv::Scalar(0, 0, 255), 3, 8, 0);
                                // std::cout << "WR:" << radius << " S:" << CV_PI * radius * radius << std::endl;
                            }
                        }
                    }
                    if (isBlack == 0 && isWhite == 1)
                    {
                        // 黑色
                        for (const auto &circle : circles2)
                        {
                            cv::Point center(cvRound(circle[0]), cvRound(circle[1]));
                            int radius = cvRound(circle[2]);
                            int area = CV_PI * radius * radius;
                            if (area > 1500)
                            {
                                largeCirclesCenters2.push_back(center);
                                // 绘制圆形中心
                                cv::circle(frame, center, 3, cv::Scalar(255, 0, 0), -1, 8, 0);
                                // 绘制圆形轮廓
                                cv::circle(frame, center, radius, cv::Scalar(0, 255, 0), 3, 8, 0);
                                // std::cout << "BR:" << radius << " S:" << CV_PI * radius * radius << std::endl;
                            }
                        }
                    }

                    // 输出保存的圆心坐标
                    // std::cout << "W: " << largeCirclesCenters << std::endl;
                    // std::cout << "B: " << largeCirclesCenters2 << std::endl;

                    // 获取被占用矩形的索引
                    if (isBlack == 1 && isWhite == 0)
                    {
                        occupiedIndices = findOccupiedRectangles(rectangleCenter, largeCirclesCenters);
                    }
                    if (isBlack == 0 && isWhite == 1)
                    {
                        occupiedIndices = findOccupiedRectangles(rectangleCenter, largeCirclesCenters2);
                    }
                    std::sort(occupiedIndices.begin(), occupiedIndices.end());
                    std::set_difference(occupiedIndices.begin(), occupiedIndices.end(), occupiedIndicesLast.begin(), occupiedIndicesLast.end(), std::back_inserter(playerPosition));
                    // // 输出被占用的矩形索引
                    // std::cout << "Occupied rectangle indices: ";
                    // for (const auto &index : occupiedIndices)
                    // {
                    //     std::cout << index << " ";
                    // }
                    // std::cout << std::endl;

                    // miniMax
                    // printBoard(board);

                    if (currentPlayer == X && !playerPosition.empty())
                    {
                        isDown == 0;
                        std::cout << "fuck:" << playerPosition[0] << std::endl;
                        std::pair<int, int> position = get_position(data, playerPosition[0]);
                        std::cout << "run player position:(" << position.first << position.second << ")" << std::endl;
                        if (board[position.first][position.second] == EMPTY)
                        {
                            board[position.first][position.second] = X;
                            currentPlayer = O;
                        }
                        else
                        {
                            cout << "Invalid move. Try again." << endl;
                        }
                    }
                    if (currentPlayer == O)
                    {
                        std::cout << "run AI" << std::endl;
                        auto move = findBestMove(board, O);
                        board[move.first][move.second] = O;
                        // 调用函数并打印结果
                        int result = get_element(data, move.first, move.second);
                        if (isBlack == 1 && isWhite == 0)
                        {
                            datatest.cmd = result;
                            datatest.dataf = result;
                        }
                        if (isBlack == 0 && isWhite == 1)
                        {
                            datatest.cmd = result + 9;
                            datatest.dataf = result + 9;
                        }
                        // sp.writeData(&datatest, sizeof(datatest));
                        std::cout << "第 " << move.first << " 行 " << move.second << " 列 输出：" << result << std::endl;
                        currentPlayer = X;
                        isDown = 1;
                    }
                    if (isDown == 1)
                    {
                        sp.writeData(&datatest, sizeof(datatest));
                    }
                    playerPosition.clear();

                    occupiedIndicesLast = occupiedIndices;

                    isPlayerDown = 0;
                    if (reflash == 1)
                    {
                        imshow("frame", frame);
                        if (isBlack == 1 && isWhite == 0)
                            imshow("gray1", gray1);
                        if (isBlack == 0 && isWhite == 1)
                            imshow("gray2", gray2);
                        waitKey(1);
                    }
                }
                // // std::cout << "run imshow" << count2 << std::endl;
                // if (waitKey(0) == 27)
                // {
                // }
            }
            // printBoard(board);
            if (isEnd == 1)
            {
                isBlack = 0;
                isWhite = 0;
                isEnd = 2;
                data = {
                    {1, 2, 3},
                    {4, 5, 6},
                    {7, 8, 9}};
                // 重新初始化board
                board = std::vector<std::vector<Player>>(BOARD_SIZE, std::vector<Player>(BOARD_SIZE, EMPTY));
                int score = evaluateBoard(board, X);
                if (score == 10)
                {
                    cout << "You win!" << endl;
                }
                else if (score == -10)
                {
                    cout << "Computer wins!" << endl;
                }
                else
                {
                    cout << "It's a draw!" << endl;
                }
            }
        }
    }
    cap.release();
    std::cout << "release" << std::endl;
    // 输出矩形中心坐标
    destroyAllWindows();
    return 0;
}

// std::vector<std::vector<int>> data = {
//     {1, 2, 3},
//     {4, 5, 6},
//     {7, 8, 9}};
// vector<vector<Player>> board(BOARD_SIZE, vector<Player>(BOARD_SIZE, EMPTY));
// Player currentPlayer = O;

// while (!isGameOver(board))
// {
//     printBoard(board);
//     if (currentPlayer == X)
//     {
//         int row, col;
//         cout << "Enter your move (row and column): ";
//         cin >> row >> col;
//         if (board[row][col] == EMPTY)
//         {
//             board[row][col] = X;
//             currentPlayer = O;
//         }
//         else
//         {
//             cout << "Invalid move. Try again." << endl;
//         }
//     }
//     else
//     {
//         auto move = findBestMove(board, O);
//         board[move.first][move.second] = O;
//         // 调用函数并打印结果
//         int result = get_element(data, move.first, move.second);
//         std::cout << "第 " << move.first << " 行 " << move.second << " 列 输出：" << result << std::endl;
//         currentPlayer = X;
//     }
// }
// printBoard(board);
// int score = evaluateBoard(board, X);
// if (score == 10)
// {
//     cout << "You win!" << endl;
// }
// else if (score == -10)
// {
//     cout << "Computer wins!" << endl;
// }
// else
// {
//     cout << "It's a draw!" << endl;
// }